<?php

namespace app\commission;

use app\models\group\Group as Model;
use app\models\group\GroupFans;
use app\models\group\GroupList;
use app\models\marketing\MarketingGroup;
use app\models\marketing\MarketingGroupLevel;
use app\models\order\OrderItem;
use app\models\order\Order;
use app\models\user\User;
use app\models\user\UserCommission;
use app\models\user\UserLevel;
use app\services\Chain;
use app\util\Debug;

class Group
{
    private $group;

    private $profit;

    private $no_win_total = 0;

    public function commission(Model $group)
    {
        $transaction = \Yii::$app->db->beginTransaction();

        try {

            $this->group = $group;

            // win
            $this->win();

            // profit
            $this->getProfit();

            // add total list
            $this->addList();

            // up level
            $this->upLevelBig();
            $this->upLevelVip();

            // award
            $this->awardBig();
            $this->awardVip();

            $transaction->commit();
        } catch (\Exception $e) {
            $transaction->rollBack();
            Debug::commission('group-fail', $e->getMessage() . $e->getFile() . '-' . $e->getLine());
        }
    }

    private function win()
    {
        $set = MarketingGroup::getLastOne();
        $win = $set->win_total;

        $ids = GroupFans::find()
            ->where(['group_id' => $this->group->id])
            ->andWhere(['status' => 1])
            ->select(['id'])
            ->column();

        shuffle($ids);
        $ids = array_slice($ids, 0, $win);
        GroupFans::updateAll(['win' => 1], ['id' => $ids]);

        // group is express (win)
        $order_ids = GroupFans::find()
            ->where(['id' => $ids])
            ->select(['order_id'])
            ->column();
        OrderItem::updateAll(['is_express' => 1], ['order_id' => $order_ids]);

        // not win
        $not_win = GroupFans::find()
            ->where(['group_id' => $this->group->id])
            ->andWhere(['status' => 1])
            ->andWhere(['win' => 0])
            ->with(['order'])
            ->asArray()
            ->all();

        /*
         * set not win
         */
        $append = $set->no_win_commission;

        foreach ($not_win as $fans) {
            // pay
            $balance = $fans['order']['use_balance'] + $fans['order']['use_money'];
            $platform_ticket = $fans['order']['use_platform_ticket'];

            // return balance
            $model = new UserCommission();
            $model->user_id = $fans['user_id'];
            $model->fans_id = $fans['user_id'];
            $model->balance = $balance;
            $model->platform_ticket = $platform_ticket;
            $model->order_id = $fans['order_id'];
            $model->group_order_id = $fans['group_id'];
            $model->status = 1;
            $model->award_type = UserCommission::$AWARD_Type['NOT_WIN_BACK'];
            $model->award_name = UserCommission::$AWARD_NAME['NOT_WIN_BACK'];
            $model->save();

            // save commission
            $model = new UserCommission();
            $model->user_id = $fans['user_id'];
            $model->fans_id = $fans['user_id'];
            $model->balance = $append;
            $model->order_id = $fans['order_id'];
            $model->group_order_id = $fans['group_id'];
            $model->status = 1;
            $model->award_type = UserCommission::$AWARD_Type['NOT_WIN'];
            $model->award_name = UserCommission::$AWARD_NAME['NOT_WIN'];
            $model->save();

            $this->no_win_total += $append;

            // save to account
            Commission::getInstance()->commissionSaveAccount($model);
        }
    }

    private function getProfit()
    {
        /*
         * win => 1
         */
        $fans = GroupFans::find()
            ->where(['group_id' => $this->group->id])
            ->andWhere(['status' => 1])
            ->andWhere(['win' => 1])
            ->with(['order', 'order.item', 'order.item.product'])
            ->asArray()
            ->all();

        $total = 0;
        foreach ($fans as $item) {

            $cost = $item['order']['item'][0]['product']['price_cost'];
            $price = $item['order']['item'][0]['product']['price'];
            $quantity = $item['order']['item'][0]['quantity'];

            $total += ($price - $cost) * $quantity;
        }

        $this->profit = $total;
    }

    private function addList()
    {
        // 0.5
        $set = MarketingGroup::getLastOne();
        $ratio = $set->start_up_pool / 100;

        $last_total = GroupList::find()
            ->orderBy(['id' => SORT_DESC])
            ->select(['total'])
            ->scalar();
        if (!$last_total) {
            $last_total = 0;
        }

        $profit = $this->profit * $ratio - $this->no_win_total;
        if ($profit < 0) {
            $profit = 0;
        }

        $model = new GroupList();
        $model->group_id = $this->group->id;
        $model->add = $profit;
        $model->total += $last_total + $model->add;
        $model->save();
    }

    // big group leader
    private function upLevelBig()
    {
        $fans_ids = GroupFans::find()
            ->where(['status' => 1])
            ->andWhere(['group_id' => $this->group->id])
            ->select(['user_id'])
            ->column();

        $referrer_ids = User::find()
            ->where(['id' => $fans_ids])
            ->andWhere(['>=', 'level', UserLevel::$keys['vip1']])
            ->select(['referrer_id'])
            ->column();

        $referrers = User::find()
            ->where(['id' => $referrer_ids])
            ->andWhere(['<', 'level', UserLevel::$keys['vip2']])
            ->all();

        $set = MarketingGroup::getLastOne();
        foreach ($referrers as $referrer) {
            // if ($referrer['level'] > UserLevel::$keys['vip2']) {
            //     continue;
            // }

            $children = Chain::getChildrenLevel($referrer->id, [
                UserLevel::$keys['vip1'],
                UserLevel::$keys['vip2'],
                UserLevel::$keys['svip1'],
                UserLevel::$keys['svip2'],
                // UserLevel::$keys['svip3'],
                // UserLevel::$keys['star1'],
                // UserLevel::$keys['star2'],
                // UserLevel::$keys['star3'],
                // UserLevel::$keys['star4'],
                // UserLevel::$keys['star5'],
                UserLevel::$keys['v1'],
                UserLevel::$keys['v2'],
                UserLevel::$keys['v3'],
                UserLevel::$keys['v5'],
                UserLevel::$keys['w1'],
                UserLevel::$keys['w2'],
                UserLevel::$keys['w3'],
            ]);

            // var_dump($set->vip2_recommend_finish_group_total);exit;

            if (count($children) >= $set->vip2_recommend_finish_group_total) {
                $referrer->level = UserLevel::$keys['vip2'];
                $referrer->save();
            }
        }
    }

    // group leader vip
    private function upLevelVip()
    {
        // $v1 = 10000;
        // $v2 = 30000;
        // $v3 = 60000;
        // $v4 = 120000;

        // $fans_ids = GroupFans::find()
        //     ->where(['status' => 1])
        //     ->andWhere(['group_id' => $this->group->id])
        //     ->select(['user_id'])
        //     ->column();

        // users in group
        // $users = User::find()
        //     ->where(['id' => $fans_ids])
        //     ->all();

        // user in all
        $users = User::find()
            ->where(['>=', 'level', UserLevel::$keys['vip1']])
            ->all();

        $level = MarketingGroupLevel::find()
            ->orderBy(['id' => SORT_DESC])
            ->asArray()
            ->all();

        foreach ($users as $user) {
            $first_children = User::find()
                ->where(['referrer_id' => $user['id']])
                ->select(['id'])
                ->column();
            $all_users = array_merge([$user['id']], $first_children);
            $total = Order::find()
                ->where(['user_id' => $all_users])
                ->andWhere(['!=', 'status', Order::$statusMapping['NON_PAYMENT']])
                ->andWhere(['!=', 'status', Order::$statusMapping['CANCEL']])
                ->sum('total_pay');

            foreach ($level as $item) {
                if ($total >= $item['amount'] && $user->group_level < $item['id']) {
                    $user->group_level = $item['id'];
                    $user->save();
                    break;
                }
            }
        }


    }

    // private function awardBig()
    // {
    //     /*
    //      * set ratio
    //      */
    //     $set = MarketingGroup::getLastOne();
    //     $ratio = $set->vip2_recommend_finish_group_award / 100;
    //
    //     $balance = $this->profit * $ratio;
    //     $user = User::find()
    //         ->where(['id' => $this->group->user_id])
    //         // ->with(['level0'])
    //         ->asArray()
    //         ->one();
    //
    //     // level
    //     if ($user['level'] >= UserLevel::$keys['vip2']) {
    //         // save commission
    //         $model = new UserCommission();
    //         $model->user_id = $user['id'];
    //         $model->fans_id = 0;
    //         $model->balance = $balance;
    //         $model->order_id = 0;
    //         $model->group_order_id = $this->group->id;
    //         $model->status = 1;
    //         $model->award_type = UserCommission::$AWARD_Type['GROUP_FINISH'];
    //         $model->award_name = UserCommission::$AWARD_NAME['GROUP_FINISH'];
    //         $model->save();
    //
    //         // save to account
    //         Commission::getInstance()->commissionSaveAccount($model);
    //     }
    // }

    private function awardBig()
    {
        /*
         * set ratio
         */
        $set = MarketingGroup::getLastOne();
        $ratio = $set->vip2_recommend_finish_group_award / 100;

        $fans_ids = GroupFans::find()
            ->where(['status' => 1])
            ->andWhere(['group_id' => $this->group->id])
            ->select(['user_id'])
            ->column();

        $referrer_ids = User::find()
            ->where(['id' => $fans_ids])
            ->select(['referrer_id'])
            ->column();

        $referrers = User::find()
            ->where(['id' => $referrer_ids])
            ->andWhere(['>=', 'level', UserLevel::$keys['vip2']])
            ->all();

        $balance = $this->profit * $ratio;
        // average
        // if (count($referrers) > 0) {
        //     $balance = $balance / count($referrers);
        // }

        if ($balance > 0) {
            foreach ($referrers as $referrer) {
                // save commission
                $model = new UserCommission();
                $model->user_id = $referrer['id'];
                $model->fans_id = 0;
                $model->balance = $balance;
                $model->order_id = 0;
                $model->group_order_id = $this->group->id;
                $model->status = 1;
                $model->award_type = UserCommission::$AWARD_Type['GROUP_FINISH'];
                $model->award_name = UserCommission::$AWARD_NAME['GROUP_FINISH'];
                $model->save();

                // save to account
                Commission::getInstance()->commissionSaveAccount($model);
            }
        }
    }

    private function awardVip()
    {
        // user in group
        // $fans_ids = GroupFans::find()
        //     ->where(['group_id' => $this->group->id])
        //     ->andWhere(['status' => 1])
        //     ->andWhere(['win' => 1])
        //     ->select(['user_id'])
        //     ->column();

        // user in all
        $user_ids = User::find()
            ->where(['>', 'group_level', 0])
            ->select(['id'])
            ->column();

        $user = User::find()
            // ->where(['id' => $fans_ids])
            ->where(['id' => $user_ids])
            // ->with(['groupLevel0'])
            ->asArray()
            ->all();

        /*
        $ratio1 = 0.1;
        $ratio2 = 0.2;
        $ratio3 = 0.3;
        $ratio4 = 0.4;
        */

        $level = MarketingGroupLevel::find()
            ->orderBy(['id' => SORT_ASC])
            ->asArray()
            ->all();

        $list = [];
        foreach ($level as &$item) {
            $item['user'] = [];

            foreach ($user as $u) {
                if ($u['group_level'] == $item['id']) {
                    array_push($item['user'], $u['id']);
                }
            }

            if (count($item['user']) > 0) {
                array_push($list, [
                    'ratio' => $item['ratio'] / count($item['user']) / 100,
                    'user' => $item['user']
                ]);
            }
        }

        $pool = GroupList::findOne(['group_id' => $this->group->id]);
        $use = 0;

        foreach ($list as $item) {
            foreach ($item['user'] as $id) {
                $balance = $pool->total * $item['ratio'];

                if ($balance > 0) {
                    $use += $balance;

                    // save commission
                    $model = new UserCommission();
                    $model->user_id = $id;
                    $model->fans_id = 0;
                    $model->balance = $balance;
                    $model->order_id = 0;
                    $model->group_order_id = $this->group->id;
                    $model->status = 0;
                    $model->month_return = 1;
                    $model->award_type = UserCommission::$AWARD_Type['GROUP_V'];
                    $model->award_name = UserCommission::$AWARD_NAME['GROUP_V'];
                    $model->save();

                    // save to account
                    Commission::getInstance()->commissionSaveAccount($model);
                }
            }
        }

        $pool->total -= $use;
        $pool->save();

    }


}